package com.qikux.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;

import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Properties;

public class RSAUtils {

    private static Properties p = new Properties();

    static {
        try {
            p.load(RSAUtils.class.getClassLoader().getResourceAsStream("rsa.properties"));
        } catch (IOException e) {
            throw new ExceptionInInitializerError("rsa.properties配置文件找不到");
        }
    }

    /**
     * 加密
     *
     * @param rawText
     * @return
     */
    public static String encrypt(String rawText) {
        String publicKey = p.getProperty("email.rsa.public.key");
        String privateKey = p.getProperty("email.rsa.private.key");
        RSA rsa = new RSA(privateKey, publicKey);
        byte[] encrypt = rsa.encrypt(rawText, KeyType.PublicKey);
        return HexUtil.encodeHexStr(encrypt);
    }

    /**
     * 解密
     * @param rawText
     * @return
     */
    public static String decrypt(String rawText) {
        String publicKey = p.getProperty("email.rsa.public.key");
        String privateKey = p.getProperty("email.rsa.private.key");
        RSA rsa = new RSA(privateKey, publicKey);
        byte[] encrypt = rsa.decrypt(HexUtil.decodeHex(rawText), KeyType.PrivateKey);
        return new String(encrypt);
    }

    /**
     * 数字签名
     * 返回的签名如果需要进行网络传输，可能需要进行URLEncode 编码
     * @param rawText
     * @return
     */
    public static String sign(String rawText) {
        String publicKey = p.getProperty("email.rsa.public.key");
        String privateKey = p.getProperty("email.rsa.private.key");
        // 进行数字签名的对象
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, privateKey, publicKey);
        // 获取签名后的结果
        byte[] sign1 = sign.sign(rawText.getBytes(StandardCharsets.UTF_8));
        // 对签名后的结果 进行 Base64编码
        String encode = Base64.encode(sign1);
        return encode ;
    }

    public static boolean verify(String rawText, String sign) {
        String publicKey = p.getProperty("email.rsa.public.key");
        String privateKey = p.getProperty("email.rsa.private.key");
        // 进行数字签名的对象
        Sign secureSign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, privateKey, publicKey);
        // 使用 URLDecode 进行解码

        // 进行 Base64解码
        byte[] decode1 = Base64.decode(sign);
        // 对内容进行认证，查看是否被篡改
        return secureSign.verify(rawText.getBytes(StandardCharsets.UTF_8), decode1);
    }

    /**
     * 生成公钥和私钥
     */
    private static void generatorKey() {
        KeyPair keyPair = SecureUtil.generateKeyPair("RSA", 512);
        // 获取私钥
        PrivateKey aPrivate = keyPair.getPrivate();
        byte[] encoded = aPrivate.getEncoded();
        System.out.println("私钥信息为:" + Base64.encode(encoded));
        PublicKey aPublic = keyPair.getPublic();
        byte[] encoded1 = aPublic.getEncoded();
        System.out.println("公钥信息为:" + Base64.encode(encoded1));
    }


    public static void main(String[] args) {
        // 生成公钥和私钥
        generatorKey();

        // 签名
        String sign = sign("hello");

        System.out.println(sign);


        //String decode = URLDecoder.decode(sign, StandardCharsets.UTF_8);
        // 认证
        System.out.println(verify("hello", sign));

        // 加密
        String encrpty = encrypt("123456");

        System.out.println(encrpty);
        // 解密
        System.out.println("decrypt(encrpty) = " + decrypt(encrpty));

    }
}
